package com.thb.pay.core.utils;

import org.apache.commons.lang3.StringUtils;

import java.util.Random;

/**
 * @类名称 NumberUtils
 * @类描述 <pre>邀请码生成器
 * **算法原理：
 *  * 1) 获取id: 1313520
 *  * 2) 使用自定义进制转为：gpm6
 *  * 3) 转为字符串，并在后面加'O'字符：gpm6o
 *  * 4）在后面随机产生若干个随机数字字符：gpm6o7
 *  * 转为自定义进制后就不会出现o这个字符，然后在后面加个'o'，这样就能确定唯一性。最后在后面产生一些随机字符进行补全。
 *  </pre>
 * @作者 lucky
 * @创建时间 2019/10/27
 * @版本 v1.01
 */
public class ShareCodeUtils {

    /**
     * 自定义进制(0,1没有加入,容易与o,l混淆)
     */
    private static final char[] DEFAULT_RESOURCE_KEY = new char[]{'6', 'W', 'E', '8', 'A', 'S', '2', 'D', 'Z', 'X', '9', 'C', '7', 'P', '5', 'I', 'K', '3', 'M', 'J', 'U', 'F', 'R', '4', 'V', 'Y', 'l', 'T', 'N', 'Q', 'B', 'G', 'H'};
    /**
     * (不能与自定义进制有重复)
     */
    private static final char NOT_REPEAT_RES = '1';

    /**
     * 序列最小长度 默认
     */
    private static final int DEFAULT_MIN_SEQUENCE_LENGTH = 6;

    public static String generateCode(long id, String customizeHexResourceKey) {
        return generateCode(id, customizeHexResourceKey, DEFAULT_MIN_SEQUENCE_LENGTH);
    }

    /**
     * @param id:                      用户id
     * @param customizeHexResourceKey: 自定义进制(0,1没有加入,容易与o,l混淆)
     * @param sequenceLength:          生成随机序列号长度
     * @方法名称
     * @功能描述 根据ID生成随机邀请码
     * @作者: lucky
     * @创建时间: 22:02 2019/10/27
     * @return: java.lang.String
     * @版本 v1.01
     **/
    public static String generateCode(long id, String customizeHexResourceKey, int sequenceLength) {
        char[] hexResourceKey = getHexResourceKey(customizeHexResourceKey);
        int hexLength = getHexLength(customizeHexResourceKey);
        if (sequenceLength <= 0) {
            sequenceLength = DEFAULT_MIN_SEQUENCE_LENGTH;
        }
        char[] buf = new char[32];
        int charPos = 32;

        while ((id / hexLength) > 0) {
            int ind = (int) (id % hexLength);
            buf[--charPos] = hexResourceKey[ind];
            id /= hexLength;
        }
        buf[--charPos] = hexResourceKey[(int) (id % hexLength)];
        String str = new String(buf, charPos, (32 - charPos));
        // 不够长度的自动随机补全
        if (str.length() < sequenceLength) {
            StringBuilder sb = new StringBuilder();
            sb.append(NOT_REPEAT_RES);
            Random rnd = new Random();
            for (int i = 1; i < sequenceLength - str.length(); i++) {
                sb.append(hexResourceKey[rnd.nextInt(hexLength)]);
            }
            str += sb.toString();
        }
        return str;
    }

    public static String generateCode(long id, int sequenceLength) {
        return generateCode(id, null, sequenceLength);
    }


    public static String generateCode(long id) {
        return generateCode(id, DEFAULT_MIN_SEQUENCE_LENGTH);
    }

    /**
     * @param code: 分享码
     * @方法名称 decodeCode
     * @功能描述 解码
     * @作者: lucky
     * @创建时间: 21:30 2019/10/27
     * @return: java.lang.Long
     **/
    public static long decodeCode(String code) {
        return decodeCode(code, null);
    }

    public static long decodeCode(String code, String customizeHexResourceKey) {
        char[] hexResourceKey = getHexResourceKey(customizeHexResourceKey);
        int hexLength = getHexLength(customizeHexResourceKey);
        char chs[] = code.toCharArray();
        long res = 0L;
        for (int i = 0; i < chs.length; i++) {
            int ind = 0;
            for (int j = 0; j < hexLength; j++) {
                if (chs[i] == hexResourceKey[j]) {
                    ind = j;
                    break;
                }
            }
            if (chs[i] == NOT_REPEAT_RES) {
                break;
            }
            if (i > 0) {
                res = res * hexLength + ind;
            } else {
                res = ind;
            }
        }
        return res;
    }


    private static char[] getHexResourceKey(String customizeHexResourceKey) {
        if (StringUtils.isNotBlank(customizeHexResourceKey)) {
            return customizeHexResourceKey.toCharArray();
        }
        return DEFAULT_RESOURCE_KEY;
    }

    private static int getHexLength(String customizeHexResourceKey) {
        if (StringUtils.isNotBlank(customizeHexResourceKey)) {
            return customizeHexResourceKey.toCharArray().length;
        }
        return DEFAULT_RESOURCE_KEY.length;
    }

    public static void main(String[] args) {
        String s = ShareCodeUtils.generateCode(522L, 30);
        System.out.println(s);
        System.out.println(ShareCodeUtils.decodeCode(s));
        s = ShareCodeUtils.generateCode(522L);
        System.out.println(ShareCodeUtils.decodeCode(s));

        s = ShareCodeUtils.generateCode(1314520L, "123456789ABCDEFGHJKLMN", 10);
        System.out.println(s);
        System.out.println(ShareCodeUtils.decodeCode(s, "123456789ABCDEFGHJKLMN"));

        System.out.println(String.valueOf(DEFAULT_RESOURCE_KEY));

    }
}
